﻿using LitJson;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Web;
using WxSDK.Config;

namespace WxSDK.Common
{
	/// <summary>
	/// 微信基础API
	/// </summary>
	public class WxBaseApi
	{
		#region 获得微信接口调用凭据(access_token)
		/// <summary>
		/// 获得微信接口调用凭据(access_token)的JSON数据，有效期2小时。与网页授权access_token不同。
		/// 成功返回：{"access_token":"ACCESS_TOKEN","expires_in":7200}。
		/// 失败返回：{"errcode":40013,"errmsg":"invalid appid"}
		/// </summary>
		/// <returns></returns>
		public static string GetAccessTokenByWxMini()
		{
			return GetAccessToken(WxConfig.WxMiniAPPID, WxConfig.WxMiniAPPSECRET);
		}

		/// <summary>
		/// 获得微信接口调用凭据(access_token)的JSON数据，有效期2小时。与网页授权access_token不同。
		/// 成功返回：{"access_token":"ACCESS_TOKEN","expires_in":7200}。
		/// 失败返回：{"errcode":40013,"errmsg":"invalid appid"}
		/// </summary>
		/// <returns></returns>
		public static string GetAccessToken()
		{
			return GetAccessToken(WxConfig.APPID, WxConfig.APPSECRET);
		}

		/// <summary>
		/// 获得微信接口调用凭据(access_token)的JSON数据，有效期2小时。与网页授权access_token不同。
		/// 成功返回：{"access_token":"ACCESS_TOKEN","expires_in":7200}。
		/// 失败返回：{"errcode":40013,"errmsg":"invalid appid"}
		/// </summary>
		/// <param name="APPID"></param>
		/// <param name="APPSECRET"></param>
		/// <returns></returns>
		public static string GetAccessToken(string APPID,string APPSECRET)
		{
			WxData data = new WxData();
			data.SetValue("appid", APPID);
			data.SetValue("secret", APPSECRET);
			data.SetValue("grant_type", "client_credential");
			string url = "https://api.weixin.qq.com/cgi-bin/token?" + data.ToUrl();
			//请求url以获取数据
			string result = HttpService.Get(url);
			Log.Debug("获得微信接口调用凭据(access_token)", "返回数据 : " + result);
			return result;
		}
		#endregion

		#region 网页授权(access_token)相关
		/// <summary>
		/// 得到网页授权的客户端URL
		/// </summary>
		/// <param name="redirect_uri">回调地址</param>
		/// <param name="state">重定向后会带上state参数，开发者可以填写a-zA-Z0-9的参数值，最多128字节</param>
		/// <param name="appid"></param>
		/// <param name="scopeType">0：snsapi_base；1：snsapi_userinfo；</param>
		/// <returns></returns>
		public static string GetWebAuthorizeUrl(string redirect_uri,string state="", string appid = "", int scopeType = 0)
		{
			if (string.IsNullOrEmpty(redirect_uri))
			{
				return "";
			}
			if (string.IsNullOrEmpty(appid))
			{
				appid = WxConfig.APPID;
			}
			redirect_uri = HttpUtility.UrlEncode(redirect_uri);
			WxData data = new WxData();
			data.SetValue("appid", appid);
			data.SetValue("redirect_uri", redirect_uri);
			data.SetValue("response_type", "code");
			data.SetValue("scope", (scopeType == 0) ? "snsapi_base" : "snsapi_userinfo");
			data.SetValue("state", state);
			string url = "https://open.weixin.qq.com/connect/oauth2/authorize?" + data.ToUrl();
			return url;
		}
		/// <summary>
		/// 通过code换取网页授权access_token(与接口调用凭据access_token不同)和openid的返回数据，正确时返回的JSON数据包如下：
		/// {
		/// "access_token":"ACCESS_TOKEN",
		/// "expires_in":7200,
		/// "refresh_token":"REFRESH_TOKEN",
		/// "openid":"OPENID",
		/// "scope":"SCOPE",
		/// "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
		/// }
		/// 其中access_token可用于获取共享收货地址。
		/// openid是微信支付jsapi支付接口统一下单时必须的参数。
		/// 更详细的说明请参考网页授权获取用户基本信息：http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
		/// </summary>
		/// <param name="code"></param>
		/// <param name="appid"></param>
		/// <param name="secret"></param>
		public static WxData GetOpenidAndAccessTokenFromCode(string code,string appid="",string secret="")
		{
			if (string.IsNullOrEmpty(appid))
			{
				appid = WxConfig.APPID;
			}
			if (string.IsNullOrEmpty(secret))
			{
				secret = WxConfig.APPSECRET;
			}
			//构造获取openid及access_token的url
			WxData data = new WxData();
			data.SetValue("appid", appid);
			data.SetValue("secret", secret);
			data.SetValue("code", code);
			data.SetValue("grant_type", "authorization_code");
			string url = "https://api.weixin.qq.com/sns/oauth2/access_token?" + data.ToUrl();
			string result = "";
			try
			{
				//请求url以获取数据
				result = HttpService.Get(url);
				Log.Debug("通过code换取网页授权access_token", "返回数据: " + result);
			}
			catch (Exception ex)
			{
				Log.Error("通过code换取网页授权失败", ex.ToString());
				throw new WxException(ex.ToString());
			}

			JsonData jd = JsonMapper.ToObject(result);
			string access_token = "";
			string openid = "";
			try
			{
				access_token = (string)jd["access_token"];
				if (!string.IsNullOrEmpty(access_token))
				{
					//获取用户openid
					openid = (string)jd["openid"];
				}
				else
				{
					Log.Error("通过code换取网页授权失败", " errcode : " + (string)jd["errcode"] + "；errmsg : " + (string)jd["errmsg"]);
				}
			}
			catch
			{
				Log.Error("通过code换取网页授权失败", " errcode : " + (string)jd["errcode"] + "；errmsg : " + (string)jd["errmsg"]);
			}
			WxData resultData = new WxData();
			resultData.SetValue("access_token", access_token);
			resultData.SetValue("openid", openid);
			return resultData;
		}

		/// <summary>
		/// 通过OpenID和AccessToken拉取用户信息的返回数据，正确时返回的JSON数据包如下：
		/// {
		///  "openid":" OPENID",		//用户的唯一标识 
		///  "nickname": NICKNAME,	//用户昵称
		///  "sex":"1",//用户的性别，值为1时是男性，值为2时是女性，值为0时是未知
		///  "province":"PROVINCE"//用户个人资料填写的省份
		///  "city":"CITY",//普通用户个人资料填写的城市
		///  "country":"COUNTRY",//国家，如中国为CN 
		///  "headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46", //用户头像，最后一个数值代表正方形头像大小（有0、46、64、96、132数值可选，0代表640*640正方形头像），用户没有头像时该项为空。若用户更换头像，原有头像URL将失效。
		///  "privilege":["PRIVILEGE1","PRIVILEGE2"],//用户特权信息，json 数组，如微信沃卡用户为（chinaunicom） 
		///  "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"//只有在用户将公众号绑定到微信开放平台帐号后，才会出现该字段。
		/// }
		/// 更详细的说明请参考：http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
		/// </summary>
		/// <param name="OpenID"></param>
		/// <param name="AccessToken">网页授权access_token</param>
		public static WxData GetUserInfoFromOpenidAndAccessToken(string OpenID, string AccessToken)
		{
			try
			{
				//构造拉取用户信息的url
				WxData data = new WxData();
				data.SetValue("access_token", AccessToken);
				data.SetValue("openid", OpenID);
				data.SetValue("lang", "zh_CN");
				string url = "https://api.weixin.qq.com/sns/userinfo?" + data.ToUrl();

				//请求url以获取数据
				string result = HttpService.Get(url);

				Log.Debug("通过OpenID和AccessToken拉取用户信息", "返回数据 : " + result);

				WxData UserInfoResult = new WxData();
				JsonData jd = JsonMapper.ToObject(result);
				if (!string.IsNullOrEmpty((string)jd["openid"]))
				{
					UserInfoResult.SetValue("openid", (string)jd["openid"]);
					UserInfoResult.SetValue("nickname", (string)jd["nickname"]);
					UserInfoResult.SetValue("sex", (int)jd["sex"]);
					UserInfoResult.SetValue("language", (string)jd["language"]);
					UserInfoResult.SetValue("city", (string)jd["city"]);
					UserInfoResult.SetValue("province", (string)jd["province"]);
					UserInfoResult.SetValue("country", (string)jd["country"]);
					UserInfoResult.SetValue("headimgurl", (string)jd["headimgurl"]);
					if (jd["privilege"].IsArray)
					{
						string strArray = "";
						JsonData jdItems = jd["privilege"];
						for (int i = 0; i < jdItems.Count; i++)
						{
							strArray = strArray + (string)jdItems[i] + ",";
						}
						strArray = strArray.TrimEnd(',');
						UserInfoResult.SetValue("privilege", strArray);
					}
					if (((IDictionary)jd).Contains("unionid"))
					{
						UserInfoResult.SetValue("unionid", (string)jd["unionid"]);
					}
				}
				else
				{
					Log.Error("通过OpenID和AccessToken拉取用户信息失败", " errcode : " + (string)jd["errcode"] + "；errmsg : " + (string)jd["errmsg"]);
				}
				return UserInfoResult;
			}
			catch (Exception ex)
			{
				Log.Error("通过OpenID和AccessToken拉取用户信息失败", ex.ToString());
				throw new WxException(ex.ToString());
			}
		}
		#endregion
	}
}
